import * as Cesium from 'cesium'

export class LayerManager {
  _viewer = null
  _imageryLayerCollection = []
  _dataSourceCollection = []
  _tilesetCollection = []
  constructor(viewer) {
    this._viewer = viewer
    this._imageryLayerCollection = viewer.imageryLayers
    this._dataSourceCollection = viewer.dataSources
  }

  get viewer() {
    return this._viewer
  }

  set viewer(value) {
    this._viewer = value
  }

  /**
   * 添加地形
   */
  async initTerrain(viewer, opt) {
    let terrainProvider
    if (opt.type === 'arcgis') {
      terrainProvider = await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl(opt.url)
    } else if (opt.type === 'ion') {
      terrainProvider = await Cesium.createWorldTerrainAsync()
    } else if (opt.type === 'mars') {
      terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl(opt.url)
    } else {
      terrainProvider = new Cesium.EllipsoidTerrainProvider()
    }

    // 添加地形
    viewer.terrainProvider = terrainProvider
  }

  /**
   * 获取图层类别
   */
  getLayerClassType(data) {
    let classType = 'imagery'
    if (['geojson'].includes(data.type)) {
      classType = 'datasource'
    } else if (data.type === '3dtiles') {
      classType = '3dtiles'
    } else {
      classType = 'imagery'
    }
    return classType
  }

  /**
   *根据ID获取图层
   */
  getLayerByIds(data) {
    const type = this.getLayerClassType(data)
    const id = data.id

    if (!this._imageryLayerCollection || !this._imageryLayerCollection.length) {
      return null
    }
    let layerArray = []
    if (type === 'imagery') {
      layerArray = this._imageryLayerCollection._layers
    } else if (type === 'datasource') {
      layerArray = this._dataSourceCollection._dataSources
    } else if (type === '3dtiles') {
      layerArray = this._tilesetCollection
    }

    for (let i = 0; i < layerArray.length; i++) {
      const layer = layerArray[i]
      const lid = layer.lid
      if (id === lid) {
        return layer
      }
    }
  }

  /**
   * 根据类型创建图层
   * @param {*} type
   * @param {*} option
   * @returns
   */
  addLayerByType(type, option) {
    let layer
    type = type.toLowerCase()
    if (type === 'geojson') {
      this.addDataSource(type, option)
    } else if (type === '3dtiles') {
      this.create3DTiles(option)
    } else {
      layer = this.addImageryProvider(type, option)
    }
    //设置图层id、type
    if (layer && option.id) {
      layer.lid = option.id
    }
    if (layer && option.ltype) {
      layer.ltype = option.type
    }
  }

  addImageryProvider(type, option) {
    let imageryProviderPromise
    switch (type) {
      case 'arcgis_dynamic':
        imageryProviderPromise = Cesium.ArcGisMapServerImageryProvider.fromUrl(
          option.url ||
          'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer',
          {
            // token: ""
          }
        )
        break
      case 'tdt':
        imageryProviderPromise = this.createTDTLayer(option)
        break
      case 'google':
        imageryProviderPromise = this.createGoogleLayer(option)
        break
      case 'wmts':
        imageryProviderPromise = new Cesium.ArcGisMapServerImageryProvider()
        break
      case 'wms':
        imageryProviderPromise = this.createWMSLayer(option)
        break
      case 'xyz':
        imageryProviderPromise = new Cesium.UrlTemplateImageryProvider({
          url: option.url
          // tilingScheme: new Cesium.GeographicTilingScheme()
          // tilingScheme: new Cesium.WebMercatorTilingScheme()
        })
        break
      case 'single':
        imageryProviderPromise = Cesium.SingleTileImageryProvider.fromUrl(
          option.url || './data/worldimage.jpeg'
        )
        break
      case 'arcgis_cache':
        imageryProviderPromise = new Cesium.ArcGisMapServerImageryProvider()
        break
      case 'gaode':
        imageryProviderPromise = this.createGaoGeLayer(option)
        break
      case 'baidu':
        imageryProviderPromise = this.createBaiDuLayer(option)
        break
      case 'tilegrid':
        imageryProviderPromise = new Cesium.GridImageryProvider()
        break
      case 'tilegrid-coor':
        imageryProviderPromise = new Cesium.TileCoordinatesImageryProvider()
        break
      case 'osm':
        imageryProviderPromise = new Cesium.OpenStreetMapImageryProvider({
          url: 'https://tile.openstreetmap.org/'
        })
        break
      // case 'geojson':
      //   this.createGeoJSONLayer(option)
      //   break
      // case '3dtiles':
      //   this.create3DTiles(option)
    }
    const layer = new Cesium.ImageryLayer.fromProviderAsync(imageryProviderPromise, {})
    this._imageryLayerCollection.add(layer)
    return layer
  }

  async addDataSource(type, option) {
    let dataSource
    switch (type) {
      case 'geojson':
        dataSource = await this.createGeoJSONLayer(option)
        break
      case 'customds':
        dataSource = this.createGeoJSONLayer(option)
        break
      case 'kml':
        dataSource = this.createGeoJSONLayer(option)
        break
      case 'czml':
        dataSource = this.createGeoJSONLayer(option)
        break
    }
    // return dataSource
  }

  /**
   *创建天地图图层
   * kvp形式的wmts服务的url请求：
   * https://t2.tianditu.gov.cn/cva_w/wmts?tk=
   * 支持4490\4326\3857坐标系的wmts服务
   * 支持的服务类型有：vec_c\vec_w\cva_c\cva_w\img_c\img_w\cia_c\cia_w
   */
  createTDTLayer(option) {
    const layertype = option.layertype
    const token = option.token
    const layer = layertype.substr(0, 3)
    const tileMatrixSetID = layertype.substring(4)

    const url =
      option.url ||
      'http://t' +
      Math.round(Math.random() * 7) +
      '.tianditu.gov.cn/' +
      layertype +
      '/wmts?tk=' +
      token

    let layerInstance = new Cesium.WebMapTileServiceImageryProvider({
      url: url,
      layer: layer,
      style: 'default',
      format: 'image/jpeg',
      tileMatrixSetID: tileMatrixSetID,
      // tileMatrixLabels : ['default028mm:0', 'default028mm:1', 'default028mm:2' ...],
      maximumLevel: 19
      // tilingScheme: new Cesium.GeographicTilingScheme()
      // tilingScheme: new Cesium.WebMercatorTilingScheme()
      // credit: new Cesium.Credit('tianditu')
    })
    return layerInstance
  }

  /**
   *创建谷歌地图图层
    m	路网
    t	地形图层
    p	带标签的地形图
    s	卫星图
    y	带标签的卫星图
    h	标签层（路名、地名等）

   */
  createGoogleLayer(option) {
    const layertype = option.layertype
    const url = `http://gac-geo.googlecnapps.cn/maps/vt?lyrs=${layertype}&x={x}&y={y}&z={z}`
    let layerInstance
    if (['m', 't', 'p', 's', 'y', 'h'].indexOf(layertype) > -1) {
      layerInstance = new Cesium.UrlTemplateImageryProvider({
        url: url
      })
    } else {
      layerInstance = new Cesium.UrlTemplateImageryProvider({
        url: 'http://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}'
      })
    }
    return layerInstance
  }

  /**
   * 创建高德地图图层
   */
  createGaoGeLayer(option) {
    let layerInstance = new Cesium.UrlTemplateImageryProvider({
      url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'
    })
    return layerInstance
  }

  /**
   * 创建百度地图图层
   */
  createBaiDuLayer(option) {
    let layerInstance = new Cesium.UrlTemplateImageryProvider({
      url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'
    })
    return layerInstance
  }

  /**
   * 创建GeoJSON图层
   */
  async createGeoJSONLayer(option) {
    const dataSource = await Cesium.GeoJsonDataSource.load(option.url, {
      stroke: Cesium.Color.HOTPINK,
      // fill: Cesium.Color.PINK,
      strokeWidth: 4
      // markerSymbol: '?'
    })
    this._dataSourceCollection.add(dataSource)
    dataSource.lid = option.id
    dataSource.ltype = option.type
  }

  /**
   * 创建GeoJSON图层
   */
  createWMSLayer(option) {
    let layer = new Cesium.WebMapServiceImageryProvider({
      url: option.url,
      layers: option.layers
      // parameters: {
      //   transparent: true,
      //   format: 'image/png'
      // },
      // srs: 'EPSG:4326'
      // proxy: new Cesium.DefaultProxy('/proxy/')
    })
    return layer
  }
  /**
   * 创建GeoJSON图层
   */
  async create3DTiles(option) {
    try {
      const constructorOpt = Object.assign({}, option.opt)
      const tileset = await Cesium.Cesium3DTileset.fromUrl(option.url, constructorOpt)
      this._viewer.scene.primitives.add(tileset)
      tileset.lid = option.id
      tileset.ltype = option.type
      this._tilesetCollection.push(tileset)
      this._viewer.zoomTo(tileset)
    } catch (error) {
      console.error(`Error creating tileset: ${error}`)
    }
  }
}
